package com.ruoyi.system.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.activity.domain.ActBusinessFlowRel;
import com.ruoyi.activity.service.IFlowService;
import com.ruoyi.activity.service.impl.ActBusinessFlowRelServiceImpl;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.enums.BusinessFlag;
import com.ruoyi.common.utils.excel.ExcelDataListener;
import com.ruoyi.common.utils.excel.ExcelImageUtil;
import com.ruoyi.system.controller.FileUploadController;
import com.ruoyi.system.domain.AssociationClapCulvert;
import com.ruoyi.system.domain.CompanyInfo;
import com.ruoyi.system.domain.TAssociationClapDetail;
import com.ruoyi.system.domain.vo.coopHan.*;
import com.ruoyi.system.domain.vo.handleRecord.HandleRecordVo;
import com.ruoyi.system.dto.coopHan.*;
import com.ruoyi.system.dto.handleRecord.HandleRecordDto;
import com.ruoyi.system.mapper.AssociationClapCulvertMapper;
import com.ruoyi.system.mapper.CompanyInfoMapper;
import com.ruoyi.system.service.IAssociationClapCulvertService;
import com.ruoyi.system.service.ICompanyInfoService;
import com.ruoyi.workflow.domain.CompanyApply;
import com.ruoyi.workflow.mapper.CompanyApplyMapper;
import com.sun.mail.util.BEncoderStream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.PictureData;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.rmi.ServerException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * <p>
 * 协拍涵表 服务实现类
 * </p>
 *
 * @author yanfu
 * @since 2024-03-01
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AssociationClapCulvertServiceImpl extends ServiceImpl<AssociationClapCulvertMapper, AssociationClapCulvert> implements IAssociationClapCulvertService {

    private final TAssociationClapDetailServiceImpl tAssociationClapDetailService;

    private final ActBusinessFlowRelServiceImpl actBusinessFlowRelService;

    private final FileUploadController fileUploadController;

    private final static String SL = "受理";
    private final static String SCJD = "审查决定";
    private final static String GZFH = "盖章发函";


    @Resource
    private IFlowService flowServiceImpl;

    @Override
    @Transactional(rollbackFor = Exception.class)
    // 保存数据
    public Long saveCulvert(CulvertDto dto) {
        return baseSave(dto);
    }

    /**
     * 公共保存方法
     */
    public Long baseSave(CulvertDto dto) {
        dto.setId(null);
        // 保存数据
        AssociationClapCulvert associationClapCulvert = new AssociationClapCulvert();
        BeanUtils.copyProperties(dto, associationClapCulvert);
        //TODO 企业id暂定部门id
        associationClapCulvert.setCorporateId(SecurityUtils.getDeptId());
        //生成协拍涵编号
        String xphNum;
        //查询表中的最后一条的编号
        DecimalFormat df = new DecimalFormat("00000");
        AssociationClapCulvert clapCulvert = getOne(Wrappers.lambdaQuery(AssociationClapCulvert.class).
                orderByDesc(AssociationClapCulvert::getCreateTime).
                last("limit 1"));
        if (Objects.isNull(clapCulvert) || StringUtils.isEmpty(clapCulvert.getXphNum())) {
            xphNum = "XPH00001";
        } else {
            String num = clapCulvert.getXphNum();
            xphNum = "XPH" + df.format(1 + Integer.parseInt(num.substring(3, 8)));
        }
        associationClapCulvert.setXphNum(xphNum);
        save(associationClapCulvert);
        List<TAssociationClapDetail> details = new ArrayList<>();
        List<ClapDetailDto> clapDetailDtos = dto.getClapDetailDtos();
        for (ClapDetailDto clapDetailDto : clapDetailDtos) {
            TAssociationClapDetail detail = new TAssociationClapDetail();
            BeanUtils.copyProperties(clapDetailDto, detail);
            detail.setCulvertId(associationClapCulvert.getId());
            //待协调
            detail.setHarmonizeState("1");
            details.add(detail);
        }
        tAssociationClapDetailService.saveBatch(details);
        //将保存好，将主表的id返回出去
        return associationClapCulvert.getId();
    }

    /**
     * 保存并提交
     */
    @Override
    public String saveAndCommit(CulvertDto dto) throws Exception {
        //有id编辑
        Long id = dto.getId();
        if (Objects.nonNull(id)) {
            putCulvert(dto);
        } else {
            //保存
            id = baseSave(dto);
        }
        return flowServiceImpl.start(id, BusinessFlag.CO_OP_HAN.getValue());
    }

    @Override
    public void delCulvert(Long id) throws ServerException {
        AssociationClapCulvert clapCulvert = getById(id);
        if (Objects.isNull(clapCulvert)) {
            throw new ServerException("数据未找到");
        }
        if (StringUtils.isNotEmpty(clapCulvert.getFlowId())) {
            throw new ServerException("数据正在审核流程中不能删除");
        }
        removeById(id);
        tAssociationClapDetailService.remove(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                eq(TAssociationClapDetail::getCulvertId, id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void putCulvert(CulvertDto dto) throws Exception {
        AssociationClapCulvert associationClapCulvert = getById(dto.getId());
        if (Objects.isNull(associationClapCulvert)) {
            throw new ServerException("数据未找到");
        }
        BeanUtils.copyProperties(dto, associationClapCulvert);
        //TODO 企业id暂定部门id
        associationClapCulvert.setCorporateId(SecurityUtils.getDeptId());
        updateById(associationClapCulvert);
        //删除详情重新添加
        tAssociationClapDetailService.remove(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                eq(TAssociationClapDetail::getCulvertId, dto.getId()));
        List<TAssociationClapDetail> details = new ArrayList<>();
        List<ClapDetailDto> clapDetailDtos = dto.getClapDetailDtos();
        for (ClapDetailDto clapDetailDto : clapDetailDtos) {
            TAssociationClapDetail detail = new TAssociationClapDetail();
            BeanUtils.copyProperties(clapDetailDto, detail);
            detail.setCulvertId(associationClapCulvert.getId());
            //待协调
            detail.setHarmonizeState("1");
            details.add(detail);
        }
        tAssociationClapDetailService.saveBatch(details);
    }

    @Override
    public Page<PageCulvertVo> pageCulvert(PageCulvertDto dto) {
        Page<PageCulvertVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        page = baseMapper.pageCulvert(page, dto);
        List<PageCulvertVo> records = page.getRecords();
        for (PageCulvertVo record : records) {
            //总数
            List<TAssociationClapDetail> list = tAssociationClapDetailService.
                    list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                            eq(TAssociationClapDetail::getCulvertId, record.getId()));
            record.setHarmony(list.size());
            //待协调
            int count = (int) list.stream().filter(item -> "1".equals(item.getHarmonizeState())).count();
            record.setNotHarmony(count);
        }
        return page;
    }

    @Override
    public List<TAssociationClapDetail> feedbackCulvert(Long id) {
        return tAssociationClapDetailService.list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                eq(TAssociationClapDetail::getCulvertId, id));
    }

    @Override
    public void harmonizeCulvert(List<Long> ids) throws ServerException {
        List<TAssociationClapDetail> details = tAssociationClapDetailService.listByIds(ids);
        for (TAssociationClapDetail detail : details) {
            String harmonizeState = detail.getHarmonizeState();
            if ("2".equals(harmonizeState)) {
                throw new ServerException(detail.getDistrict() + "的" + detail.getPosition() + "数据已经是协调状态");
            }
            detail.setHarmonizeState("2");
        }
        tAssociationClapDetailService.updateBatchById(details);
    }

    @Override
    public List<HandleRecordVo> handleRecord(HandleRecordDto dto) {
        Long userId = SecurityUtils.getUserId();
        List<HandleRecordVo> handleRecordVos = baseMapper.handleRecord(dto, userId);
        return handleRecordVos.stream().
                sorted(Comparator.comparing(HandleRecordVo::getSubmitTime).reversed()).
                collect(Collectors.toList());
    }

    /**
     * app端协拍涵详情
     *
     * @param id 协拍涵id
     * @return CulvertDetailVo
     */
    @Override
    public CulvertDetailVo detailCulvert(Long id) throws ServerException {
        CulvertDetailVo vo = new CulvertDetailVo();
        AssociationClapCulvert culvert = getById(id);
        if (Objects.isNull(culvert)) {
            throw new ServerException("数据不存");
        }
        BeanUtils.copyProperties(culvert, vo);
        List<TAssociationClapDetail> list = tAssociationClapDetailService.
                list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                        eq(TAssociationClapDetail::getCulvertId, culvert.getId()));
        vo.setClapDetails(list);
        String flowId = culvert.getFlowId();
        if (StringUtils.isEmpty(flowId)) {
            vo.setFlowState(0);
        } else {
            ActBusinessFlowRel flowRel = actBusinessFlowRelService.
                    getOne(Wrappers.lambdaQuery(ActBusinessFlowRel.class).
                            eq(ActBusinessFlowRel::getProcInstId, flowId));
            if (Objects.nonNull(flowRel)) {
                vo.setFlowState(flowRel.getFlowState());
            }
        }
        return vo;
    }

    @Override
    public Page<PageCulvertApprovalVo> getApprovalPage(PageCulvertDto dto) {
        Page<PageCulvertApprovalVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        Long userId = SecurityUtils.getUserId();
        dto.setApprovalUserId(userId);
        Page<PageCulvertApprovalVo> res = this.getBaseMapper().getApprovalPage(page, dto);
        List<PageCulvertApprovalVo> records = res.getRecords();
        for (PageCulvertApprovalVo record : records) {
            List<TAssociationClapDetail> list = tAssociationClapDetailService.
                    list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                            eq(TAssociationClapDetail::getCulvertId, record.getId()));
            //协拍场景数
            record.setSceneNumber(list.size());
        }
        return res;
    }

    @Autowired
    private CompanyInfoMapper companyInfoMapper;

    /**
     * 审核详情
     */
    @Override
    public CulvertApprovalDetailVo getApprovalDetail(Long id) {
        CulvertApprovalDetailVo vo = new CulvertApprovalDetailVo();
        AssociationClapCulvert culvert = getById(id);
        BeanUtils.copyProperties(culvert, vo);
        List<TAssociationClapDetail> list = tAssociationClapDetailService.
                list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                        eq(TAssociationClapDetail::getCulvertId, id));
        vo.setDetails(list);
        //拍摄地
        String districtsConcatenated = list.stream()
                .map(TAssociationClapDetail::getDistrict)
                .filter(district -> district != null && !district.isEmpty())
                .collect(Collectors.joining(","));
        vo.setDistrict(districtsConcatenated);
        // 获取最早的captureStartTime
        Optional<Date> earliestStartTime = list.stream()
                .map(TAssociationClapDetail::getCaptureStartTime).
                filter(Objects::nonNull)
                .min(Date::compareTo);

        // 获取最晚的captureEndTime
        Optional<Date> latestEndTime = list.stream()
                .map(TAssociationClapDetail::getCaptureEndTime).
                filter(Objects::nonNull)
                .max(Date::compareTo);
        earliestStartTime.ifPresent(vo::setCaptureStartTime);
        latestEndTime.ifPresent(vo::setCaptureEndTime);

        if(StringUtils.isNotBlank(culvert.getProductionUnit())){
            CompanyInfo companyInfo= companyInfoMapper.selectCompanyInfoByCompanyName(culvert.getProductionUnit());
            if(companyInfo!=null){
                CulvertApprovalCompanyVo culvertApprovalCompanyVo=new CulvertApprovalCompanyVo();
                culvertApprovalCompanyVo.setCompanyId(companyInfo.getCompanyId().toString());
                culvertApprovalCompanyVo.setCompanyName(companyInfo.getCompanyName());
                culvertApprovalCompanyVo.setBusinessLicense(companyInfo.getBusinessLicensePath());
                culvertApprovalCompanyVo.setLegalPersonName(companyInfo.getLegalRepresentative());
                culvertApprovalCompanyVo.setLegalPersonPhone(companyInfo.getLegalRepresentativePhone());
                vo.setCompanyVo(culvertApprovalCompanyVo);
            }
        }
        return vo;
    }

    @Override
    public Page<PageCulvertNoticeVo> pagePublicityCulvert(PageCulvertNoticeDto dto) {
        Page<PageCulvertNoticeVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        page = baseMapper.pagePublicityCulvert(dto, page);
        return page;
    }

    @Override
    public CulvertNoticeDetailVo noticeDetail(Long id) {
        CulvertNoticeDetailVo vo = new CulvertNoticeDetailVo();
        AssociationClapCulvert clapCulvert = getById(id);
        BeanUtils.copyProperties(clapCulvert, vo);
        vo.setNoticeTime(clapCulvert.getCreateTime());
        List<TAssociationClapDetail> list = tAssociationClapDetailService.
                list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                        eq(TAssociationClapDetail::getCulvertId, id));
        if (CollectionUtils.isEmpty(list)) return vo;
        String xpUnit = list.stream().
                map(TAssociationClapDetail::getCoordinatingUnit).
                collect(Collectors.joining(","));
        vo.setXpUnit(xpUnit);
        return vo;
    }

    @Override
    public List<CulvertExcelVo> importCert(MultipartFile file, HttpServletRequest request) throws Exception {
        List<CulvertExcelVo> vos;
        try (InputStream inputStream = file.getInputStream()) {
            vos = EasyExcel.read(inputStream, CulvertExcelVo.class, new ExcelDataListener<CulvertExcelVo>()).sheet().doReadSync();
        } catch (Exception e) {
            throw new ServerException("excel解析失败 " + e.getMessage());
        }
        //解析图片
        Map<String, PictureData> map = ExcelImageUtil.getPictureFromExcel(file, 1);
        if (CollectionUtils.isEmpty(map)) return vos;
        Set<String> keySet = map.keySet();
        for (String s : keySet) {
            int index = Integer.parseInt(s) - 1;
            PictureData picData = map.get(s);
            //后缀名
            String extension = picData.suggestFileExtension();
            byte[] data = picData.getData();
            MockMultipartFile file1 = new MockMultipartFile("file",
                    "拍摄场景实景图片" + s + "." + extension,
                    "multipart/form-data",
                    data
            );
            ResponseEntity<String> entity = fileUploadController.uploadFile(file1, request);
            String body = entity.getBody();
            vos.get(index).setShotLocation(body);
        }
        return vos;
    }

    @Override
    public List<CulvertApprovalDetailExportVo> export(CulvertHarmonizeDto dto) {
        List<CulvertApprovalDetailExportVo> exportVos = new ArrayList<>();
        List<Long> ids = dto.getIds();
        List<AssociationClapCulvert> associationClapCulverts = list(Wrappers.lambdaQuery(AssociationClapCulvert.class).
                in(AssociationClapCulvert::getId, ids));
        for (AssociationClapCulvert associationClapCulvert : associationClapCulverts) {
            CulvertApprovalDetailExportVo exportVo = new CulvertApprovalDetailExportVo();
            BeanUtils.copyProperties(associationClapCulvert, exportVo);
            List<TAssociationClapDetail> list = tAssociationClapDetailService.
                    list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                            eq(TAssociationClapDetail::getCulvertId, associationClapCulvert.getId()));
            exportVo.setDetails(list);

            for (TAssociationClapDetail detail : list) {
                String shotLocation = detail.getShotLocation();
                try {
                    // 正则表达式，匹配一个或多个中文字符
                    Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]+");
                    Matcher matcher = pattern.matcher(shotLocation);
                    // 找到并打印所有匹配的中文部分
                    while (matcher.find()) {
                        String group = matcher.group();
                        String encodedUrlPart = URLEncoder.encode(group, "UTF-8");
                        shotLocation = shotLocation.replace(group, encodedUrlPart);
                    }
                    detail.setShotLocation(shotLocation);
                } catch (UnsupportedEncodingException e) {
                    log.error("获取图片:{}失败：{}", shotLocation, e.getMessage());
                }
            }
            //拍摄地
            String districtsConcatenated = list.stream()
                    .map(TAssociationClapDetail::getDistrict)
                    .filter(district -> district != null && !district.isEmpty())
                    .collect(Collectors.joining(","));
            exportVo.setDistrict(districtsConcatenated);
            // 获取最早的captureStartTime
            Optional<Date> earliestStartTime = list.stream()
                    .map(TAssociationClapDetail::getCaptureStartTime).
                    filter(Objects::nonNull)
                    .min(Date::compareTo);

            // 获取最晚的captureEndTime
            Optional<Date> latestEndTime = list.stream()
                    .map(TAssociationClapDetail::getCaptureEndTime).
                    filter(Objects::nonNull)
                    .max(Date::compareTo);
            earliestStartTime.ifPresent(exportVo::setCaptureStartTime);
            latestEndTime.ifPresent(exportVo::setCaptureEndTime);
            exportVos.add(exportVo);
        }
        return exportVos;
    }

    /**
     * 协拍涵办理申请【受理】列表
     * @param dto
     * @return
     */
    @Override
    public Page<PageCulvertApprovalVo> getAcceptancePage(PageCulvertDto dto) {
        Page<PageCulvertApprovalVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        Long userId = SecurityUtils.getUserId();
        dto.setApprovalUserId(userId);
        Page<PageCulvertApprovalVo> res = this.getBaseMapper().getAcceptancePage(page, dto, SL);
        List<PageCulvertApprovalVo> records = res.getRecords();
        for (PageCulvertApprovalVo record : records) {
            List<TAssociationClapDetail> list = tAssociationClapDetailService.
                    list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                            eq(TAssociationClapDetail::getCulvertId, record.getId()));
            //协拍场景数
            record.setSceneNumber(list.size());
        }
        return res;
    }

    /**
     * 协拍涵办理申请【审查决定】列表
     * @param dto
     * @return
     */
    @Override
    public Page<PageCulvertApprovalVo> getReviewDecisionPage(PageCulvertDto dto) {
        Page<PageCulvertApprovalVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        Long userId = SecurityUtils.getUserId();
        dto.setApprovalUserId(userId);
        Page<PageCulvertApprovalVo> res = this.getBaseMapper().getAcceptancePage(page, dto, SCJD);
        List<PageCulvertApprovalVo> records = res.getRecords();
        for (PageCulvertApprovalVo record : records) {
            List<TAssociationClapDetail> list = tAssociationClapDetailService.
                    list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                            eq(TAssociationClapDetail::getCulvertId, record.getId()));
            //协拍场景数
            record.setSceneNumber(list.size());
        }
        return res;
    }

    /**
     * 协拍涵办理申请【盖章发函】列表
     * @param dto
     * @return
     */
    @Override
    public Page<PageCulvertApprovalVo> getStampSendLetterPage(PageCulvertDto dto) {
        Page<PageCulvertApprovalVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        Long userId = SecurityUtils.getUserId();
        dto.setApprovalUserId(userId);
        Page<PageCulvertApprovalVo> res = this.getBaseMapper().getAcceptancePage(page, dto, GZFH);
        List<PageCulvertApprovalVo> records = res.getRecords();
        for (PageCulvertApprovalVo record : records) {
            List<TAssociationClapDetail> list = tAssociationClapDetailService.
                    list(Wrappers.lambdaQuery(TAssociationClapDetail.class).
                            eq(TAssociationClapDetail::getCulvertId, record.getId()));
            //协拍场景数
            record.setSceneNumber(list.size());
        }
        return res;
    }


    @Resource
    private CompanyApplyMapper companyApplyMapper;
    @Resource
    private ICompanyInfoService companyInfoService;
    @Override
    public CompanyInfo getCompanyDesc(String id) {
        log.info(id);
        CompanyApply companyApply = companyApplyMapper.selectInfoById(id);
        CompanyInfo companyInfo=companyInfoService.selectCompanyInfoById(Long.parseLong(companyApply.getCompanyId()));
        companyInfo.setRelatedFilePath(companyApply.getApplicationFileUrl());
        companyInfo.setRelatedFilesPath(companyApply.getApplicationFilesUrl());
        companyInfo.setBusinessLicensePath(companyApply.getApplicationImageUrl());
        return companyInfo;
    }
}

